#!/bin/sh
###############################################################
# SPDX-License-Identifier: BSD-2-Clause-Patent
# Copyright (c) 2019 Tomer Eliyahu (Intel)
# This code is subject to the terms of the BSD+Patent license.
# See LICENSE file for more details.
###############################################################

SIG_TERM=-15
SIG_KILL=-9

dbg() {
    [ "$VERBOSE" = "true" ] && echo "$@"
}

err() {
    printf '\033[1;31m'"$@\n"'\033[0m'
}

success() {
    printf '\033[1;32m'"$@\n"'\033[0m'
}

run() {
    dbg "$*"
    "$@" || exit $?
}

killall_program() {
    PROGRAM_NAME=$1
    if [ "$#" -eq 2 ]; then
        KILL_SIG=$2
    else
        KILL_SIG=$SIG_KILL
    fi
    for PID in $(pgrep -f $PROGRAM_NAME); do
        echo "kill $KILL_SIG $PID $PROGRAM_NAME";
        kill $KILL_SIG $PID > /dev/null 2>&1;
    done
}

platform_init() {
    echo "platform init..."
    base_mac=46:55:66:77
    bridge_ip=192.168.100.140
    control_ip=192.168.250.140
    
    ip link add @BEEROCKS_BRIDGE_IFACE@ address "${base_mac}:00:00" type bridge
    ip link add @BEEROCKS_BH_WIRE_IFACE@ type dummy
    ip link add wlan0 address "${base_mac}:00:10" type dummy
    ip link add wlan2 address "${base_mac}:00:20" type dummy
    ip link set dev wlan0 up
    ip link set dev wlan2 up
    for iface in wlan0 wlan2 @BEEROCKS_BH_WIRE_IFACE@ $DATA_IFACE
    do
        echo "add $iface to @BEEROCKS_BRIDGE_IFACE@"
        nmcli d set "$iface" managed no
        ip link set dev "$iface" master @BEEROCKS_BRIDGE_IFACE@
        ip addr flush "$iface"
    done
    ip addr add "$control_ip"/24 dev "$CONTROL_IFACE"
    ip addr add "$bridge_ip"/24 dev @BEEROCKS_BRIDGE_IFACE@
    ip link set @BEEROCKS_BRIDGE_IFACE@ up
}

platform_deinit() {
    echo "platform deinit"
    for iface in wlan0 wlan2 @BEEROCKS_BH_WIRE_IFACE@ $DATA_IFACE
    do
        echo "remove $iface from @BEEROCKS_BRIDGE_IFACE@"
        ip link set dev "$iface" nomaster
        nmcli d set "$iface" managed yes
    done
    ip link del wlan0
    ip link del wlan2
    ip link del @BEEROCKS_BH_WIRE_IFACE@
    ip link del @BEEROCKS_BRIDGE_IFACE@
}

prplmesh_platform_db_init() {
    management_mode=${1-Multi-AP-Controller-and-Agent}
    operating_mode=${2-Gateway}

    mkdir -p @PLATFORM_DB_PATH_TEMP@
    {
        echo "management_mode=${management_mode}"
        echo "operating_mode=${operating_mode}"
        echo "wired_backhaul=1"
    } > @PLATFORM_DB_PATH_TEMP@/prplmesh_platform_db
}

prplmesh_framework_init() {
    echo "prplmesh_framework_init - starting local_bus and ieee1905_transport processes..."
    @BEEROCKS_INSTALL_PATH@/bin/local_bus &
    @BEEROCKS_INSTALL_PATH@/bin/ieee1905_transport &
}

prplmesh_framework_deinit() {
    echo "prplmesh_framework_init - killing local_bus and ieee1905_transport processes..."
    killall_program local_bus
    killall_program ieee1905_transport
}

prplmesh_controller_start() {
    echo "prplmesh_controller_start - start beerocks_controller process..."
    @BEEROCKS_INSTALL_PATH@/bin/beerocks_controller &
}

prplmesh_controller_stop() {
    echo "prplmesh_controller_stop - stopping beerocks_controller process..."
    killall_program beerocks_controller
}

prplmesh_agent_start() {
    echo "prplmesh_agent_start - start beerocks_agent process..."
    @BEEROCKS_INSTALL_PATH@/bin/beerocks_agent &
}

prplmesh_agent_stop() {
    echo "prplmesh_agent_stop - stopping beerocks_agent process..."
    killall_program beerocks_agent
}

prplmesh_delete_logs() {
    echo "deleting logs"
    rm -rf /tmp/beerocks/logs
    rm -rf /tmp/${SUDO_USER:-${USER}}/beerocks/logs
}

start_function() {
    echo "$0: start"
    [ `id -u` -ne 0 ] && echo "$0: warning - this commands needs root privileges so might not work (are you root?)"

    [ "@BWL_TYPE@" = "DUMMY" -a "$PLATFORM_INIT" = "true" ] && platform_init
    [ "@BTL_TYPE@" = "LOCAL_BUS" ] && prplmesh_framework_init
    case "$PRPLMESH_MODE" in
        CA | ca)
            prplmesh_platform_db_init "Multi-AP-Controller-and-Agent"
            prplmesh_controller_start
            prplmesh_agent_start
            ;;
        C | c)
            prplmesh_platform_db_init "Multi-AP-Controller"
            prplmesh_controller_start
            ;;
        A | a)
            prplmesh_platform_db_init "Multi-AP-Agent" "WDS-Repeater"
            prplmesh_agent_start
            ;;
        * ) err "unsupported mode: $PRPLMESH_MODE"; usage; exit 1 ;;
    esac
}

stop_function() {
    echo "$0: stop"
    [ `id -u` -ne 0 ] && echo "$0: warning - this commands needs root privileges so might not work (are you root?)"

    [ "@BWL_TYPE@" = "DUMMY" -a "$PLATFORM_INIT" = "true" ] && platform_deinit
    [ "@BTL_TYPE@" = "LOCAL_BUS" ] && prplmesh_framework_deinit
    [ "$PRPLMESH_MODE" = "CA" -o "$PRPLMESH_MODE" = "C" ] && prplmesh_controller_stop
    [ "$PRPLMESH_MODE" = "CA" -o "$PRPLMESH_MODE" = "A" ] && prplmesh_agent_stop
    [ "$DELETE_LOGS" = "true" ] && prplmesh_delete_logs
}

main_agent_operational() {
    pgrep -la beerocks_agent | grep -v wlan > /dev/null 2>&1 || return 1
    grep -q 'CONNECTED --> OPERATIONAL' "$1/beerocks_agent.log"
}

radio_agent_operational() {
    pgrep -la beerocks_agent | grep $2 | grep -v grep > /dev/null 2>&1 || return 1
    grep -q 'CSA' "$1/beerocks_agent_$2.log"
}

report() {
    msg="$1"; shift
    if "$@"; then
        success "OK $msg"
    else
        err "FAIL $msg"
        error=1
    fi
}

status_function() {
    echo "$0: status"

    pgrep -la beerocks
    pgrep -la ieee1905_transport
    pgrep -la local_bus

    # check for operational status
    LOGS_PATH=@BEEROCKS_TMP_PATH@/logs/

    error=0
    report "Main agent operational" main_agent_operational $LOGS_PATH
    report "@BEEROCKS_WLAN1_IFACE@ radio agent operational" radio_agent_operational $LOGS_PATH @BEEROCKS_WLAN1_IFACE@
    report "@BEEROCKS_WLAN2_IFACE@ radio agent operational" radio_agent_operational $LOGS_PATH @BEEROCKS_WLAN2_IFACE@

    [ "$VERBOSE" = "true" -a $error = 1 ] && {
        cat $LOGS_PATH/beerocks_agent.log
        cat $LOGS_PATH/beerocks_agent_@BEEROCKS_WLAN1_IFACE@.log
        cat $LOGS_PATH/beerocks_agent_@BEEROCKS_WLAN2_IFACE@.log
    }

    return $error
}

usage() {
    echo "usage: $(basename $0) {start|stop|restart|status} [-hvsmdCD]"
}

main() {
    OPTS=`getopt -o 'hvm:sdC:D:' --long verbose,help,mode:skip-platform,delete-logs,iface-ctrl,iface-data -n 'parse-options' -- "$@"`

    if [ $? != 0 ] ; then err "Failed parsing options." >&2 ; usage; exit 1 ; fi

    eval set -- "$OPTS"

    while true; do
        case "$1" in
            -v | --verbose)       VERBOSE=true; shift ;;
            -h | --help)          usage; exit 0; shift ;;
            -m | --mode)          PRPLMESH_MODE="$2"; shift; shift ;;
            -s | --skip-platform) PLATFORM_INIT=false; shift ;;
            -d | --delete-logs)   DELETE_LOGS=true; shift ;;
            -C | --iface-ctrl)    CONTROL_IFACE="$2"; shift; shift ;;
            -D | --iface-data)    DATA_IFACE="$2"; shift; shift ;;
            -- ) shift; break ;;
            * ) err "unsupported argument $1"; usage; exit 1 ;;
        esac
    done

    dbg VERBOSE=$VERBOSE
    dbg PLATFORM_INIT=$PLATFORM_INIT
    dbg DELETE_LOGS=$DELETE_LOGS

    case $1 in
        "start")
            start_function
            ;;
        "stop")
            stop_function
            ;;
        "restart")
            stop_function
            start_function
            ;;
        "status")
            status_function
            ;;
        *)
            err "unsupported argument \"$1\""; usage; exit 1 ;;
    esac

    # Give write permissions
    chmod -R +o+w /tmp/${SUDO_USER:-${USER}}
}

VERBOSE=false
PLATFORM_INIT=@BEEROCKS_PLATFORM_INIT@
DELETE_LOGS=false
CONTROL_IFACE=enp0s25
DATA_IFACE=enx00ee22aa28ef
PRPLMESH_MODE="CA" # CA = Controller & Agent, A = Agent only, C = Controller only

# Export MultiAP libs folder
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@BEEROCKS_INSTALL_PATH@/lib

main $@
